#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/reboot.h>
#include <openssl/sha.h>
#include "ota_version.h"
#include "../thirdparty/log.h"

/*为指定文件生成sha1码*/
static char *gen_sha1(char *filepath)
{
    FILE *file = fopen(filepath, "rb");
    if (!file)
    {
        perror("无法打开文件");
        return NULL;
    }

    unsigned char buffer[4096];
    unsigned char digest[SHA_DIGEST_LENGTH];
    SHA_CTX sha_ctx;

    SHA1_Init(&sha_ctx);

    size_t bytesRead;
    while ((bytesRead = fread(buffer, 1, sizeof(buffer), file)) > 0)
    {
        SHA1_Update(&sha_ctx, buffer, bytesRead);
    }

    fclose(file);

    SHA1_Final(digest, &sha_ctx);

    char *sha1_str = (char *)malloc(SHA_DIGEST_LENGTH * 2 + 1);
    if (!sha1_str)
    {
        perror("内存分配失败");
        return NULL;
    }

    for (int i = 0; i < SHA_DIGEST_LENGTH; ++i)
    {
        sprintf(&sha1_str[i * 2], "%02x", digest[i]);
    }

    sha1_str[SHA_DIGEST_LENGTH * 2] = '\0';

    return sha1_str;
}

/**
 * @brief 检查远端服务器上的程序版本并更新
 *
 * @return int 成功返回0  失败返回-1
 */
int ota_version_check_and_update(void)
{
    /*1.查询远端的http服务器上的程序版本信息*/
    version_t *ota_version;
    ota_version = ota_http_curl_getversion(OTA_SERVER_URI_INFO);
    if (ota_version == NULL)
    {
        log_error("get version fail\n");
        return -1;
    }
    /*2.若服务器上的程序版本高于当前程序版本*/
    if (ota_version->major > VERSION_MAJOR ||
        (ota_version->major == VERSION_MAJOR && ota_version->minor > VERSION_MINOR) ||
        (ota_version->major == VERSION_MAJOR && ota_version->minor == VERSION_MINOR && ota_version->patch > VERSION_PATCH))
    {
        /*2.1下载最新版本*/
        int res = ota_http_curl_download(OTA_SERVER_URI_DOWNLOAD, OTA_LOCAL_FILE_PATH);
        if (res == -1)
        {
            log_error("ota download file fail\n");
            free(ota_version->sha1);
            free(ota_version);
            return -1;
        }
        /*2.2为下载后的文件生成sha1码与服务器上的sha1码进行比对*/
        char *file_sha1 = gen_sha1(OTA_LOCAL_FILE_PATH);
        // log_info("http_sever_sha1:%s\n",ota_version->sha1);
        // log_info("gateway_sha1:%s\n",file_sha1);
        if (strcmp(file_sha1, ota_version->sha1) == 0)
        {
            /*2.3若比对一致说明下载的文件正常没有残缺或错乱重启程序*/
            log_info("sha1 as same as download file,reboot\n");
            free(ota_version->sha1); // 释放内存
            free(ota_version);
            reboot(RB_AUTOBOOT); // 重启程序
        }
        else
        { /*2.4若不一致说明下载的文件不正确*/
            log_error("sha1 is different with download file,delete\n");
            /*2.5删除下载的文件*/
            unlink(OTA_LOCAL_FILE_PATH);
            /*2.6释放内存资源*/
            free(ota_version->sha1);
            free(ota_version);
            return -1;
        }
    }
    log_info("version is already the lastest and is not need update\n");
    return 0;
}

/*定时每天检查版本并更新*/
void ota_version_check_daily(void)
{
    while (1)
    {
        sleep(24 * 60 *60);
        ota_version_check_and_update();
    }
    

}

void ota_version_printf(void)
{
    printf("current version: %d.%d.%d\n",VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH);
}
